package com.zhulei.biji.suanfa.pace;

/**
 * @description:
 * @author: zhulei
 * @create: 2025-03-21 13:33
 **/
public class MaximumOr {
    /**
     * 给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 k 。每一次操作中，你可以选择一个数并将它乘 2 。
     * <p>
     * 你最多可以进行 k 次操作，请你返回 nums[0] | nums[1] | ... | nums[n - 1] 的最大值。
     * <p>
     * a | b 表示两个整数 a 和 b 的 按位或 运算。
     * <p>
     * 示例 1：
     * <p>
     * 输入：nums = [12,9], k = 1
     * 输出：30
     * 解释：如果我们对下标为 1 的元素进行操作，新的数组为 [12,18] 。此时得到最优答案为 12 和 18 的按位或运算的结果，也就是 30 。
     * 示例 2：
     * <p>
     * 输入：nums = [8,1,2], k = 2
     * 输出：35
     * 解释：如果我们对下标 0 处的元素进行操作，得到新数组 [32,1,2] 。此时得到最优答案为 32|1|2 = 35 。
     * 提示：
     * <p>
     * 1 <= nums.length <= 105
     * 1 <= nums[i] <= 109
     * 1 <= k <= 15
     * Related Topics
     * 贪心
     * 位运算
     * 数组
     * 前缀和
     * <p>
     * 👍 56
     * 👎 0
     *
     */

    /**
     * suf 是所有后缀和数组
     * @param nums
     * @param k
     * @return
     */
    public static long maximumOr(int[] nums, int k) {
        int n = nums.length;
//        suf 是所有后缀和数组
        long[] suf = new long[n + 1];
        for (int i = n - 1; i >= 0; i--) {
            suf[i] = suf[i + 1] | nums[i];
        }
        //temp 是当前i 下面的前缀和
        long res =0 ,temp = 0;
        for (int i = 0; i < n; i++) {
            // temp + num【i】 + tuf【i+1】 通过前缀和+当前+后缀和就可以获取当前i下面进行k操作后的结果
            res = Math.max(res,temp | suf[i+1] | (long) nums[i] << k);
            temp = temp | nums[i];
        }
        return res;
    }

    public static void main(String[] args) {
        int[] nums = {12,9};

        System.out.println(maximumOr(nums,1));
    }
}
